﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace WPFPractice.Utils
{
    internal class NativeMethods
    {
        #region SetWindowPos

        /// <summary>
        /// 改变窗口的位置与状态
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="hWndInsertAfter">窗口的 Z 顺序
        /// 0:在前面,1:在后面,HWND(-1):在前面, 位于任何顶部窗口的前面,HWND(-2):在前面, 位于其他顶部窗口的后面
        /// </param>
        /// <param name="X">位置</param>
        /// <param name="Y">位置</param>
        /// <param name="cx">大小</param>
        /// <param name="cy">大小</param>
        /// <param name="uFlags">选项</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        #endregion SetWindowPos

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// 获取窗体句柄
        /// </summary>
        /// <param name="lpClassName"></param>
        /// <param name="lpWindowName"></param>
        /// <returns></returns>
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        /// <summary>
        /// 获取窗体句柄
        /// </summary>
        /// <param name="hwndParent"></param>
        /// <param name="hwndChildAfter"></param>
        /// <param name="lpClassName"></param>
        /// <param name="lpWindowName"></param>
        /// <returns></returns>
        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName,
            string lpWindowName);

        /// <summary>
        /// 调用Win32 API设置目标窗体大小，位置
        /// </summary>
        /// <param name="hWnd">目标句柄</param>
        /// <param name="x">目标窗体新位置X轴坐标</param>
        /// <param name="y">目标窗体新位置Y轴坐标</param>
        /// <param name="nWidth">目标窗体新宽度</param>
        /// <param name="nHeight">目标窗体新高度</param>
        /// <param name="bRepaint">是否刷新窗体</param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "MoveWindow")]
        public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);

        #region PostMessage

        /// <summary>
        /// 消息发送
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

        #endregion PostMessage

        /// <summary>
        /// 显示/隐藏窗口
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="nCmdShow"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);

        /// <summary>
        /// 窗口是否可见
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool BringWindowToTop(IntPtr hWnd);

        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        [DllImport("user32.dll")]
        public static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);

        /// <summary>
        /// 是否最小化
        /// </summary>
        /// <param name="hwnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool IsIconic(IntPtr hwnd);

        /// <summary>
        /// 设置WebBrowser的Cookie
        /// </summary>
        /// <param name="lpszUrlName">url</param>
        /// <param name="lbszCookieName">Cookie名称</param>
        /// <param name="lpszCookieData">Cookie值</param>
        /// <returns></returns>
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);

        [DllImport("shell32.dll")]
        public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, Constants.ShowCommands nShowCmd);

        public class Constants
        {
            #region ShowWindowAsync

            public const int SW_HIDE = 0;
            public const int SW_SHOWNORMAL = 1;
            public const int SW_SHOWMINIMIZED = 2;
            public const int SW_SHOWMAXIMIZED = 3;
            public const int SW_SHOWNOACTIVATE = 4;
            public const int SW_RESTORE = 9;
            public const int SW_SHOWDEFAULT = 10;

            #endregion ShowWindowAsync

            #region SetWindowPos uFlags

            /// <summary>
            /// 忽略 cx、cy, 保持大小
            /// </summary>
            public const UInt32 SWP_NOSIZE = 0x0001;

            /// <summary>
            /// 忽略 X、Y, 不改变位置
            /// </summary>
            public const UInt32 SWP_NOMOVE = 0x0002;

            /// <summary>
            /// 忽略 hWndInsertAfter, 保持 Z 顺序
            /// </summary>
            public const UInt32 SWP_NOOWNERZORDER = 0x0200;

            /// <summary>
            ///
            /// </summary>
            public const UInt32 SWP_SHOWWINDOW = 0x0040;

            #endregion SetWindowPos uFlags

            public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);

            #region PostMessage

            public const int WM_SYSCOMMAND = 0x0112;
            public const int SC_CLOSE = 0xF060;

            #endregion PostMessage

            #region mouse_event dwFlags

            public const int MOUSEEVENTF_MOVE = 0x0001;      // 移动鼠标
            public const int MOUSEEVENTF_LEFTDOWN = 0x0002;  // 模拟鼠标左键按下
            public const int MOUSEEVENTF_LEFTUP = 0x0004;    // 模拟鼠标左键抬起
            public const int MOUSEEVENTF_RIGHTDOWN = 0x0008; // 模拟鼠标右键按下
            public const int MOUSEEVENTF_RIGHTUP = 0x0010;   // 模拟鼠标右键抬起
            public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;// 模拟鼠标中键按下
            public const int MOUSEEVENTF_MIDDLEUP = 0x0040;  // 模拟鼠标中键抬起
            public const int MOUSEEVENTF_ABSOLUTE = 0x8000;  // 标示是否采用绝对坐标

            #endregion mouse_event dwFlags

            #region ShowCommands ShellExecute方法用

            public enum ShowCommands : int
            {
                SW_HIDE = 0,
                SW_SHOWNORMAL = 1,
                SW_NOrmAL = 1,
                SW_SHOWMINIMIZED = 2,
                SW_SHOWMAXIMIZED = 3,
                SW_MAXIMIZE = 3,
                SW_SHOWNOACTIVATE = 4,
                SW_SHOW = 5,
                SW_MINIMIZE = 6,
                SW_SHOWMINNOACTIVE = 7,
                SW_SHOWNA = 8,
                SW_RESTORE = 9,
                SW_SHOWDEFAULT = 10,
                SW_FORCEMINIMIZE = 11,
                SW_MAX = 11
            }

            #endregion

        }

        internal struct Rect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        public class WindowRect
        {
            public int Left { get; }
            public int Top { get; }
            public int Right { get; }
            public int Bottom { get; }
            public int Width { get; }
            public int Height { get; }

            internal WindowRect(Rect rect)
            {
                this.Left = rect.Left;
                this.Top = rect.Top;
                this.Right = rect.Right;
                this.Bottom = rect.Bottom;
                this.Height = Bottom - Top;
                this.Width = Right - Left;
            }

            public override string ToString()
            {
                return $"Left:{Left},Right:{Right},Top:{Top},Bottom:{Bottom},Height:{Height},Width:{Width}";
            }
        }

        internal delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam);
    }
}
